# -*- coding: utf-8 -*-

"""
Module implementing MeasureDialog.
"""

from PyQt4.QtGui import *
from PyQt4.QtCore import *

from ui_gen.Ui_measure_dialog import Ui_Dialog

import geolib.units as units
from qpynygeolib.mapwidgets import GraphicsMapFrame

UNITS_DIST_LABELS = ("Kilometres", "Metres", "Centimetres", "Miles", "Yards", "Feet", "Inches")
UNITS_DIST_VALUES = ("km", "m", "cm", "mi", "yd", "ft", "in")

UNITS_AREA_LABELS = ("Square Kilometres", "Hectares", "Square Metres", "Square Miles", "Acres", "Square Feet")
UNITS_AREA_VALUES = ("km2", "ha", "m2", "mi2", "acre", "ft2")

class MeasureDialog(QDialog, Ui_Dialog):
    """
    Signals:
    showing(bool) - emitted when the dialog is shown or closed
    """
    def __init__(self, mapframe=None, parent = None):
        """
        Constructor
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.values = (0, 0, 0)
        self.savedValues = []
        self.mapframe = mapframe
        self.__setupCombobox(self.unitDistance, UNITS_DIST_LABELS)
        self.__setupCombobox(self.unitPerimeter, UNITS_DIST_LABELS)
        self.__setupCombobox(self.unitArea, UNITS_AREA_LABELS)
        self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
    
    def __setupCombobox(self, box, values):
        box.clear()
        for label in values:
            box.addItem(QString(label))
    
    def __refreshSavedValues(self):
        self.savedList.clear()
        for item in self.savedValues:
            self.savedList.addItem(QListWidgetItem("%.3f %s" % item))
    
    def __saveValue(self, valueIndex, unitArray, unitIndex):
        value = units.convertTo(self.values[valueIndex], unitArray[unitIndex])
        label = units.label(unitArray[unitIndex])
        self.savedValues.append((value, label))
        self.__refreshSavedValues()
    
    def setValues(self, valueTuple=None):
        if valueTuple is not None:
            self.values = valueTuple
        distance, perimeter, area = self.values
        distance = self.__convert(distance, UNITS_DIST_VALUES, self.unitDistance.currentIndex())
        perimeter = self.__convert(perimeter, UNITS_DIST_VALUES, self.unitPerimeter.currentIndex())
        area = self.__convert(area, UNITS_AREA_VALUES, self.unitArea.currentIndex())
        self.txtDistance.setText(self.__stringify(distance, self.precisionDistance.value()))
        self.txtPerimeter.setText(self.__stringify(perimeter, self.precisionArea.value()))
        self.txtArea.setText(self.__stringify(area, self.precisionArea.value()))
    
    def __convert(self, val, values, index):
        return units.convertTo(val, values[index])
    
    def __stringify(self, val, precision):
        if precision == 0:
            form = "%i"
        else:
            form = "%." + str(precision) + "f"
            
        return form % val
    
    @pyqtSignature("int")
    def on_tabWidget_currentChanged(self, current):
        if current == 1:
            self.mapframe.setMeasureArea(True)
        else:
            self.mapframe.setMeasureArea(False)
    
    @pyqtSignature("")
    def on_clearSaved_clicked(self):
        """
        Slot documentation goes here.
        """
        self.savedValues = []
        self.__refreshSavedValues()
    
    @pyqtSignature("")
    def on_areaCopy_clicked(self):
        """
        Slot documentation goes here.
        """
        QClipboard.setText(self.txtArea.text())
    
    @pyqtSignature("")
    def on_areaSave_clicked(self):
        """
        Slot documentation goes here.
        """
        self.__saveValue(2, UNITS_AREA_VALUES, self.unitArea.currentIndex())
    
    @pyqtSignature("int")
    def on_unitArea_currentIndexChanged(self, index):
        """
        Slot documentation goes here.
        """
        self.setValues()
    
    @pyqtSignature("int")
    def on_precisionArea_valueChanged(self, p0):
        """
        Slot documentation goes here.
        """
        self.setValues()
    
    @pyqtSignature("")
    def on_perimeterCopy_clicked(self):
        """
        Slot documentation goes here.
        """
        QClipboard.setText(self.txtPerimeter.text())
    
    @pyqtSignature("")
    def on_perimeterSave_clicked(self):
        """
        Slot documentation goes here.
        """
        self.__saveValue(1, UNITS_DIST_VALUES, self.unitPerimeter.currentIndex())
    
    @pyqtSignature("int")
    def on_unitPerimeter_currentIndexChanged(self, index):
        """
        Slot documentation goes here.
        """
        self.setValues()
    
    @pyqtSignature("")
    def on_distanceCopy_clicked(self):
        """
        Slot documentation goes here.
        """
        QClipboard.setText(self.txtDistance.text())
    
    @pyqtSignature("")
    def on_distanceSave_clicked(self):
        """
        Slot documentation goes here.
        """
        self.__saveValue(0, UNITS_DIST_VALUES, self.unitDistance.currentIndex())
    
    @pyqtSignature("int")
    def on_unitDistance_currentIndexChanged(self, index):
        """
        Slot documentation goes here.
        """
        self.setValues()
    
    @pyqtSignature("int")
    def on_precisionDistance_valueChanged(self, p0):
        """
        Slot documentation goes here.
        """
        self.setValues()
        
    def closeEvent(self, event):
        self.saveWindowSettings()
        self.emit(SIGNAL("showing(bool)"), False)
        
    def showEvent(self, event):
        self.restoreWindowSettings()
        self.emit(SIGNAL("showing(bool)"), True)
        self.mapframe.setTool(GraphicsMapFrame.TOOL_MEASURE)

    def restoreWindowSettings(self):
        settings = QSettings("MeasureDialog")
        size = settings.value("MeasureDialog/Size", None)
        position = settings.value("MeasureDialog/Position", None)
        
        unitDistance = settings.value("MeasureDialog/UnitDistance", QVariant(0))
        unitPerimeter = settings.value("MeasureDialog/UnitPerimeter", QVariant(0))
        unitArea = settings.value("MeasureDialog/UnitArea", QVariant(0))
        
        precisionDistance = settings.value("MeasureDialog/PrecisionDistance", QVariant(2))
        precisionArea = settings.value("MeasureDialog/PrecisionArea", QVariant(2))
        
        tabIndex = settings.value("MeasureDialog/CurrentTabIndex", QVariant(0))
        
        if position is not None:
            self.move(position.toPoint())
        if size is not None:
            self.resize(size.toSize())
        
        self.unitDistance.setCurrentIndex(unitDistance.toInt()[0])
        self.unitPerimeter.setCurrentIndex(unitPerimeter.toInt()[0])
        self.unitArea.setCurrentIndex(unitArea.toInt()[0])
        
        self.precisionDistance.setValue(precisionDistance.toInt()[0])
        self.precisionArea.setValue(precisionArea.toInt()[0])
        
        indexInt = tabIndex.toInt()[0]
        self.tabWidget.setCurrentIndex(indexInt)
        self.mapframe.setMeasureArea(indexInt == 1)
    
    def saveWindowSettings(self):
        settings = QSettings("MeasureDialog")
        settings.setValue("MeasureDialog/Size", QVariant(self.size()))
        settings.setValue("MeasureDialog/Position", QVariant(self.pos()))
        
        settings.setValue("MeasureDialog/UnitDistance", QVariant(self.unitDistance.currentIndex()))
        settings.setValue("MeasureDialog/UnitPerimeter", QVariant(self.unitPerimeter.currentIndex()))
        settings.setValue("MeasureDialog/UnitArea", QVariant(self.unitArea.currentIndex()))
        
        settings.setValue("MeasureDialog/PrecisionDistance", QVariant(self.precisionDistance.value()))
        settings.setValue("MeasureDialog/PrecisionArea", QVariant(self.precisionArea.value()))
        
        settings.setValue("MeasureDialog/CurrentTabIndex", QVariant(self.tabWidget.currentIndex()))
        
        del settings
